#include "Enum.h"
#include "StringSerializable.h"
class EnumStringSerializable: public IStringSerializable
{
public:
    EnumStringSerializable(CEnumBase* InEnumType)
    {
        EnumType=InEnumType;
    }

    virtual CString ToString(const void* Instance) const override
    {
        return EnumType->SerializeToString(Instance);
    }
    virtual void FromString(const CString& InString,void * InInstance) const override
    {
        EnumType->DeserializeFromString(InString,InInstance);
    }
protected:
    CEnumBase* EnumType;
};

CEnumBase::CEnumBase(
    TMap<int64_t /*Value */  ,CString /* Value name*/ > InValues
    ,STypeID InTypeID
    ,ETypeFlags InExtraFlags
    )
    :CType(InTypeID
    ,InExtraFlags | ETypeFlags::Enum
     )
{
    Values=InValues;
    StringSerializable=new EnumStringSerializable(this);
}


CString CEnumBase::GetValueName(const CAny &InAny)
{
    assert(InAny.GetType()==this);
    return GetValueName(*(int*)InAny.GetPointer());
}

int64_t CEnumBase::GetValue(const CString &InName) const
{
    for(auto& Pair:Values)
    {
        if(Pair.Value==InName)
        {
            return Pair.Key;
        }
    }

    assert(false&& "It is a in valid enum value name");
    return 0;
}


CString CEnumBase::SerializeToString(const void *InInstance) const
{
    auto Name=Values.Find(*(const int64_t*)InInstance);
    if(Name)
    {
        return *Name;
    }
    return  CString(*(int64_t*)InInstance); 
}

void CEnumBase::DeserializeFromString(const CString &InString, void *InInstance) const
{
    if(InString.IsInt())
    {
        *(int64_t*)InInstance=InString.ToInt64();
        return;
    }

    *(int64_t*)InInstance=GetValue(InString);
}
